﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using AutoMapper;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using PublishNews.Entities;
using PublishNews.Models;
using PublishNews.Repositories;
using PublishNews.Utils;

namespace PublishNews.Controllers
{
    public class NewsApiController : BaseApiController<News, NewsModel>
    {
        private INewsRepository newsRepository;
        private const int m_PageSize = 10;
        public UserManager<User> UserManager { get; private set; }


        public NewsApiController(INewsRepository repository)
            : base(repository)
        {
            newsRepository = repository;
            UserManager = new UserManager<User>(new UserStore<User>(new PublishNewsContext()));
        }

        public override IHttpActionResult Get()
        {
            var entities = Repository.DbSet().OrderByDescending(x => x.UpdatedDate).ThenByDescending(x => x.CreatedDate);
            var model = Mapper.Map<List<NewsModel>>(entities);
            model = FormatNews(model);

            return Ok(model);
        }

        public override async Task<IHttpActionResult> GetBy(Guid id)
        {
            var entity = await Repository.GetBy(id);
            if (entity == null)
            {
                return NotFound();
            }

            var model = Mapper.Map<NewsModel>(entity);
            model.Content = "<html><body>" + model.Content + "</body></html>";

            return Ok(model);
        }


        public async Task<IHttpActionResult> GetNewsByCategoryAndLocation(Guid categoryId, Guid locationId)
        {
            var entity = await newsRepository.GetNewsByCategoryAndLocation(categoryId, locationId);
            var model = Mapper.Map<List<NewsModel>>(entity);
            model = FormatNews(model);

            if (model == null)
            {
                return NotFound();
            }
            model = model.OrderByDescending(x => x.CreatedDate).ThenBy(x => x.Title).ToList();

            return Ok(model);
        }

        public async Task<IHttpActionResult> GetNewsByCategoryAndLocation(Guid categoryId, Guid locationId,
                                                                          int pageIndex,int pageSize)
        {
            if(pageSize == 0)
            {
                pageSize = m_PageSize;
            }
            pageIndex = pageIndex - 1;

            var entity = await newsRepository.GetNewsByCategoryAndLocation(categoryId, locationId, pageIndex, pageSize);
            var model = Mapper.Map<List<NewsModel>>(entity);
            model = FormatNews(model);

            if (model == null)
            {
                return NotFound();
            }
            model = model.OrderByDescending(x => x.CreatedDate).ThenBy(x => x.Title).ToList();

            return Ok(model);
        }

        public async Task<IHttpActionResult> GetNewsByUserId(string userId)
        {
            var entity = await newsRepository.GetNewsByUserId(userId);
            var model = Mapper.Map<List<NewsModel>>(entity);
            model = FormatNews(model);

            if (model == null)
            {
                return NotFound();
            }

            return Ok(model);
        }

        public async Task<IHttpActionResult> GetNewsByUserId(string userId, Guid categoryId, Guid locationId)
        {
            var entity = await newsRepository.GetNewsByUserId(userId, categoryId, locationId);
            var model = Mapper.Map<List<NewsModel>>(entity);
            model = FormatNews(model);

            if (model == null)
            {
                return NotFound();
            }

            return Ok(model);
        }


        public async Task<IHttpActionResult> PostNews()
        {
            HttpResponseMessage result = null;
            var httpRequest = HttpContext.Current.Request;


            var entity = new News();

            try
            {

                foreach (var key in httpRequest.Form.AllKeys)
                {
                    string val = httpRequest.Form[key];
                    if (key == "title" || key == "Title")
                    {
                        entity.Title = val;
                    }
                    if (key == "content" || key == "Content")
                    {
                        entity.Content = val;
                    }
                    if (key == "categoryId" || key == "CategoryId")
                    {
                        if (!string.IsNullOrEmpty(val))
                        {
                            entity.CategoryId = Guid.Parse(val);
                        }
                        else
                        {
                            string defaultSetting = ConfigurationManager.AppSettings["DefaultCategoryId"];
                            Guid defaultCategoryId = new Guid();
                            Guid.TryParse(defaultSetting, out defaultCategoryId);
                            if (defaultCategoryId != Guid.Empty)
                            {
                                entity.CategoryId = defaultCategoryId;
                            }
                        }
                    }
                    if (key == "locationId" || key == "LocationId")
                    {
                        if (!string.IsNullOrEmpty(val))
                        {
                            entity.LocationId = Guid.Parse(val);
                        }
                    }
                   
                    if (key == "userId" || key == "UserId")
                    {
                        if (!string.IsNullOrEmpty(val))
                        {
                            entity.UserId = val;
                        }
                    }
                    if (key == "phoneNumber" || key == "PhoneNumber")
                    {
                        if (!string.IsNullOrEmpty(val))
                        {
                            entity.PhoneNumber = val;
                        }
                    }
                }

                Uri uri = HttpContext.Current.Request.Url;
                string host = "";
                if (uri.Port != 80)
                {
                    host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;
                }
                else
                {
                    host = uri.Scheme + Uri.SchemeDelimiter + uri.Host;
                }

                if (httpRequest.Files.Count > 0)
                {
                    for (int i = 0; i < httpRequest.Files.Count; i++)
                    {
                        var hpf = httpRequest.Files[i];
                        string extension = Path.GetExtension(hpf.FileName);
                        var oldFileName = Path.GetFileName(hpf.FileName);
                        string newFileName = Guid.NewGuid().ToString() + extension;

                        if (hpf != null && hpf.ContentLength > 0)
                        {
                            var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Images/"), newFileName);
                            hpf.SaveAs(path);
                        }

                        entity.Content = entity.Content.Replace("#image" + (i + 1), "<img width='100%' src='" + host + "/Images/" + newFileName + "' alt=''/>");
                    }

                }

                entity.CreatedBy = User.Identity.GetUserName();
                entity.CreatedDate = DateTime.Now;

                await Repository.Add(entity);
                if (string.IsNullOrEmpty(entity.UserId))
                {
                    var user = UserManager.FindById(entity.UserId);
                    if (user != null)
                    {
                        user.NumberOfNews++;
                        UserManager.Update(user);
                    }
                }
                return Ok(new { id = entity.Id });
            }
            catch (System.Exception e)
            {
                return Ok(e.Message);
            }
        }

        private List<NewsModel> FormatNews(List<NewsModel> model)
        {
            foreach (var news in model)
            {
                news.Content = HtmlRemoval.StripTagsCharArray(news.Content);
            }
            return model;
        }

        public async Task<IHttpActionResult> PostNewsJson(NewsModel model)
        {
            try
            {
                if (model != null)
                {
                    var entity = new News();

                    Uri uri = HttpContext.Current.Request.Url;
                    string host = "";
                    if (uri.Port != 80)
                    {
                        host = uri.Scheme + Uri.SchemeDelimiter + uri.Host + ":" + uri.Port;
                    }
                    else
                    {
                        host = uri.Scheme + Uri.SchemeDelimiter + uri.Host;
                    }

                    entity.Content = model.Content;
                    if (model.Images != null && model.Images.Count > 0)
                    {
                        for (int i = 0; i < model.Images.Count; i++)
                        {
                            string newFileName = Guid.NewGuid().ToString() + ".png";
                            SaveByteArrayAsImage(newFileName, model.Images[i]);

                            entity.Content = entity.Content.Replace("#image" + (i + 1), "<img width='100%' src='" + host + "/Images/" + newFileName + "' alt=''/>");
                        }

                    }

                    if (model.CategoryId.HasValue)
                    {
                        entity.CategoryId = model.CategoryId.Value;
                    }
                    else
                    {
                        string defaultSetting = ConfigurationManager.AppSettings["DefaultCategoryId"];
                        Guid defaultCategoryId = new Guid();
                        Guid.TryParse(defaultSetting, out defaultCategoryId);
                        if (defaultCategoryId != Guid.Empty)
                        {
                            entity.CategoryId = defaultCategoryId;
                        }
                    }
                    entity.Title = model.Title;
                    entity.LocationId = model.LocationId;
                    entity.UserId = model.UserId;
                    entity.PhoneNumber = model.PhoneNumber;

                    entity.CreatedBy = User.Identity.GetUserName();
                    entity.CreatedDate = DateTime.Now;

                    await Repository.Add(entity);

                    if (!string.IsNullOrEmpty(entity.UserId))
                    {
                        var user = UserManager.FindById(entity.UserId);
                        if (user != null)
                        {
                            user.NumberOfNews++;
                            UserManager.Update(user);
                        }
                    }
                    return Ok(new { id = entity.Id });

                }
                return Ok(false);
            }
            catch (Exception e)
            {
                return Ok(e.Message);
            }
        }

        private void SaveByteArrayAsImage(string fullOutputPath, string base64String)
        {
            byte[] bytes = Convert.FromBase64String(base64String);

            Image image;
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                image = Image.FromStream(ms);
            }
            var path = Path.Combine(HttpContext.Current.Server.MapPath("~/Images/"), fullOutputPath);

            image.Save(path, System.Drawing.Imaging.ImageFormat.Png);
        }
    }

    public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
    {
        public CustomMultipartFormDataStreamProvider(string path) : base(path) { }
        public override string GetLocalFileName(HttpContentHeaders headers)
        {
            return Guid.NewGuid() + headers.ContentDisposition.FileName.Replace("\"", string.Empty);
        }
    }
}
